/*
  C语言支持

  Container:
    array
	ansi_string
	unicode_string
    single_list
	double_list
    map

  Algorithm:
	base64
 */
#ifndef	__C_UTILS_2012_04_15__
#define	__C_UTILS_2012_04_15__

#ifdef __cplusplus
extern "C" {
#endif

/* 定义一些宏开关 */
#ifdef NO_C_UTILS_DLL
	/* 不作为DLL,作为源代码时的描述 */
	#define	C_UTILS_DLL
	#define C_UTILS_API

#else
	/* 作为DLL,判断是导入(使用dll)还是导出(创建dll) */
	#ifdef C_UTILS_DLL_EXPORTS
		#define C_UTILS_DLL __declspec(dllexport)
	#else
		#define C_UTILS_DLL __declspec(dllimport)
	#endif
	/* 作为dll时,一般用stdcall约定比较好 */
	#define C_UTILS_API __stdcall

#endif
/* 声明一个API */
#define C_UTILS_DECL_API(ret) C_UTILS_DLL ret C_UTILS_API
/* 实现一个API */
#define C_UTILS_IMPL_API(ret) ret C_UTILS_API
/* 编写可变参API必须使用cdecl约定 */
#define C_UTILS_DECL_CDECL_API(ret) C_UTILS_DLL ret __cdecl
#define C_UTILS_IMPL_CDECL_API(ret) ret __cdecl

/* Container::array */

/* array 存储一组数据,并能自动增长. */
struct array;
typedef size_t (C_UTILS_API * fn_array_increment)( struct array * arr );   /*自动增长量*/
typedef struct array
{
	unsigned char * base;     /*数据地址*/
	size_t count;          /*当前大小*/
	size_t max_count;          /*最大容量*/
	size_t elem_size;          /*元素大小*/
	fn_array_increment increment;   /*自动增长量*/
} array;

/* 创建一个max_count个元素,每个元素elem_size字节的数组,返回字节数 */
C_UTILS_DECL_API(int) array_create( array * arr, size_t max_count, size_t elem_size, fn_array_increment increment/* = NULL*/ );
/* 销毁一个数组 */
C_UTILS_DECL_API(void) array_destroy( array * arr );
/* 释放多余 */
C_UTILS_DECL_API(void) array_free_extra( array * arr );
/* 增加元素,返回索引 */
C_UTILS_DECL_API(int) array_add( array * arr, void * elem, size_t count );
/* 从index开始删除count个元素,返回当前个数 */
C_UTILS_DECL_API(int) array_del( array * arr, int index, int count );
/* 获取元素 */
C_UTILS_DECL_API(void *) array_get( array * arr, int index );
/* 设置元素 */
C_UTILS_DECL_API(void) array_set( array * arr, int index, void * elem );
/* 克隆数组 */
C_UTILS_DECL_API(array) array_clone( array * arr );
C_UTILS_DECL_API(array) array_clone_direct( void * p, size_t count, size_t elem_size );

#define array_get_val( type, arr, index ) ( (type *)array_get( (arr), (index) ) )
#define array_set_val( type, arr, index, val ) do { array_set( (arr), (index), &val ); } while(0)

/* 定义一个数组并产生相关的函数 */
#define define_array(type)\
typedef array array_##type;\
static int array_##type##_create( array_##type * arr, size_t max_count, fn_array_increment increment ) { return array_create( arr, max_count, sizeof(type), increment ); }\
static int array_##type##_adds( array_##type * arr, type * elem, size_t count ) { return array_add( arr, elem, count ); }\
static int array_##type##_add( array_##type * arr, type elem ) { return array_add( arr, &elem, 1 ); }\
static type * array_##type##_get_ptr( array_##type * arr, int index ) { return (type *)array_get( arr, index ); }\
static type array_##type##_get( array_##type * arr, int index ) { return *(type *)array_get( arr, index ); }\
static void array_##type##_set( array_##type * arr, int index, type elem ) { array_set( arr, index, &elem ); }\
static void array_##type##_destroy( array_##type * arr ) { array_destroy(arr); }\
static void array_##type##_free_extra( array_##type * arr ) { array_free_extra(arr); }\
static int array_##type##_del(  array_##type * arr, int index, int count ) { return array_del( arr, index, count ); }\
static array_##type array_##type##_clone( array_##type * arr ) { return array_clone(arr); }\
static array_##type array_##type##_clone_direct( type * p, size_t count ) { return array_clone_direct( p, count, sizeof(type) ); }

/* Container::xstring */
typedef struct ansi_string
{
	char * val;
	size_t length;
	size_t count;
	size_t max_count;
} ansi_string;

C_UTILS_DECL_API(int) ansi_string_create( ansi_string * str, size_t max_length );
C_UTILS_DECL_API(void) ansi_string_destroy( ansi_string * str );
C_UTILS_DECL_API(void) ansi_string_free_extra( ansi_string * str );
C_UTILS_DECL_API(int) ansi_string_assign( ansi_string * str, char * s );
C_UTILS_DECL_API(int) ansi_string_append( ansi_string * str, char * s );
C_UTILS_DECL_API(int) ansi_string_append_str( ansi_string * str, ansi_string * s );
C_UTILS_DECL_API(int) ansi_string_erase( ansi_string * str, int index, int length );
C_UTILS_DECL_API(ansi_string) ansi_string_clone( ansi_string * str );
C_UTILS_DECL_API(ansi_string) ansi_string_clone_direct( char * s );

typedef struct unicode_string
{
	wchar_t * val;
	size_t length;
	size_t count;
	size_t max_count;
} unicode_string;

C_UTILS_DECL_API(int) unicode_string_create( unicode_string * str, size_t max_length );
C_UTILS_DECL_API(void) unicode_string_destroy( unicode_string * str );
C_UTILS_DECL_API(void) unicode_string_free_extra( unicode_string * str );
C_UTILS_DECL_API(int) unicode_string_assign( unicode_string * str, wchar_t * s );
C_UTILS_DECL_API(int) unicode_string_append( unicode_string * str, wchar_t * s );
C_UTILS_DECL_API(int) unicode_string_append_str( unicode_string * str, unicode_string * s );
C_UTILS_DECL_API(int) unicode_string_erase( unicode_string * str, int index, int length );

#ifdef UNICODE
	typedef unicode_string xstring;
	#define string_create unicode_string_create
	#define string_destroy unicode_string_destroy
	#define string_free_extra unicode_string_free_extra
	#define string_assign unicode_string_assign
	#define string_append unicode_string_append
	#define string_append_str unicode_string_append_str
	#define string_erase unicode_string_erase
	#define string_clone unicode_string_clone
	#define string_clone_direct unicode_string_clone_direct
#else
	typedef ansi_string xstring;
	#define string_create ansi_string_create
	#define string_destroy ansi_string_destroy
	#define string_free_extra ansi_string_free_extra
	#define string_assign ansi_string_assign
	#define string_append ansi_string_append
	#define string_append_str ansi_string_append_str
	#define string_erase ansi_string_erase
	#define string_clone ansi_string_clone
	#define string_clone_direct ansi_string_clone_direct

#endif


/*
Algorithm:
	base64
 */
typedef unsigned char byte;
define_array(byte)
C_UTILS_DECL_API(ansi_string) base64_encode( byte * buf, size_t size );
C_UTILS_DECL_API(array_byte) base64_decode( ansi_string * str );

#ifdef __cplusplus
}
#endif

#endif /* __C_UTILS_2012_04_15__ */
